/* @flow */

import {extend, warn} from 'core/util/index'

/**
 * Runtime helper for rendering <slot>
 * 该方法用于处理<slot>标签，该方法返回插槽对应的Vnode的数组，用于替代
 * <slot>标签的位置，注意该方法返回值处的注释。
 * 解析当前组件中的slot标签时，需要使用父组件传递过来的slot的信息
 */
export function renderSlot(name: string, //slot标签上的name属性的值
                           fallback: ?Array<VNode>, //slot标签内部的子元素的虚拟dom对象
                           props: ?Object, //slot标签上的特性
                           bindObject: ?Object //通过v-bind指令绑定的对象，用于作用域插槽
): ?Array<VNode> {
  const scopedSlotFn = this.$scopedSlots[name]
  if (scopedSlotFn) { // scoped slot
    props = props || {}
    if (bindObject) {
      props = extend(extend({}, bindObject), props)
    }
    return scopedSlotFn(props) || fallback
  } else {
    const slotNodes = this.$slots[name]
    // warn duplicate slot usage
    if (slotNodes && process.env.NODE_ENV !== 'production') {
      slotNodes._rendered && warn(
        `Duplicate presence of slot "${name}" found in the same render tree ` +
        `- this will likely cause render errors.`,
        this
      )
      slotNodes._rendered = true
    }
    /**
     * 注意这里，是关键。
     * 示例：
     * root组件：
     * <div>
     *     <one><div slot="hello">hello</div></one>
     * </div>
     * one组件：
     * <div>
     *     <slot name="hello"></slot>
     *     <slot name="go"><div>go</div></slot>
     * </div>
     *
     * 其中对于one组件来说，this.$slots存储着[{hello:Vnode}]，可见，没有name为'go'的插槽的信息，并且自始至终也不会存在'go'的信息，
     * 而在处理one组件的name为'go'的slot插槽时，会使用该插槽内部的'<div>go</div>'生成的Vnode，也就是该方法
     * 中的fallback参数，该参数中存储着slot标签内部的子标签生成的Vnode对象
     */
    return slotNodes || fallback
  }
}
